﻿using System;
using System.Net;

using RabbitMQ.Client;

using RpcClient.Helper;
using RpcClient.Queue.Model;
using RpcClient.Rabbitmq.Model;

using RpcHelper;

namespace RpcClient.Rabbitmq
{
    internal class RabbitmqQueue : IDisposable
    {
        private ConnectionFactory _Factory = null;
        private IConnection _Connection = null;
        private AmqpTcpEndpoint[] _EndPoint = null;
        private readonly RabbitmqConfig _Config = null;
        private readonly string _Expiration;
        private bool _IsMany = false;

        public RabbitmqConfig Config => this._Config;

        public RabbitmqQueue(RabbitmqConfig config)
        {
            this._Config = config;
            this._Expiration = config.Expiration.ToString();
            this._Init();
        }
        public virtual void Dispose()
        {
            if (this._Connection != null)
            {
                this._Connection.Close();
                this._Connection.Dispose();
            }
        }

        protected virtual void _Init()
        {
            this._Factory = new ConnectionFactory
            {
                AutomaticRecoveryEnabled = true,
                UserName = this._Config.UserName,
                Password = this._Config.Pwd,
                VirtualHost = this._Config.VirtualHost,
                ClientProvidedName = this._Config.ClientProvidedName,
                RequestedHeartbeat = TimeSpan.FromSeconds(60)
            };
            if (this._Config.Servers.Length == 1)
            {
                QueueCon con = this._Config.Servers[0];
                if (con.ServerIp != null)
                {
                    IPEndPoint address = QueueHelper.GetServer(con.ServerIp, 5672);
                    this._Factory.HostName = address.Address.ToString();
                    this._Factory.Port = address.Port;
                }
                else
                {
                    this._Factory.Uri = con.ServerUri;
                }
            }
            else
            {
                this._IsMany = true;
                this._EndPoint = this._Config.Servers.ConvertAll(a =>
                 {
                     if (a.ServerIp != null)
                     {
                         IPEndPoint address = QueueHelper.GetServer(a.ServerIp, 5672);
                         return new AmqpTcpEndpoint(address.Address.ToString(), address.Port);
                     }
                     return new AmqpTcpEndpoint(a.ServerUri);
                 });
            }
            this._Connection = this._GetConnection();
        }

        public IModel CreateChannel()
        {
            return this._Connection.CreateModel();
        }
        public IBasicProperties GetProperties(IModel channel, MsgProperties pro)
        {
            IBasicProperties props = channel.CreateBasicProperties();
            pro.InitProperties(props);
            return props;
        }
        public IBasicProperties GetProperties(IModel channel)
        {
            IBasicProperties props = channel.CreateBasicProperties();
            props.ContentType = "application/json";
            props.ContentEncoding = "utf-8";
            if (this.Config.IsLasting)
            {
                props.DeliveryMode = 2;
            }
            else
            {
                props.DeliveryMode = 1;
            }
            props.Timestamp = new AmqpTimestamp(DateTime.Now.ToLong());
            props.Expiration = this._Expiration;
            return props;
        }
        private IConnection _GetConnection()
        {
            if (this._IsMany)
            {
                return this._Factory.CreateConnection(this._EndPoint);
            }
            return this._Factory.CreateConnection();
        }


    }
}
